/**
worker做的定时器是微任务
setInterval里面的函数执行是宏任务
* */
class PreciseInterval {
  timer1 = null; // 定时器对象
  timer2 = null; // worker定时器
  delay = null; // 定时器延迟
  callback = null; // 回调函数
  interValStatus = ''; // 定义定时器当前状态
  copyFunc = null;
  immediate = true; // 是否立即返回结果
  constructor(callback, delay, immediate = true) {
    this.callback = callback;
    this.delay = delay;
    this.immediate = immediate;
    this._openWorkerInterval(); // 创建一个worker
    this._start(); // 创建对象默认开启定时器
    this.copyFunc = this._visibilitychange.bind(this);
    document.addEventListener('visibilitychange', this.copyFunc); // 开启一个浏览器休眠监视器
  }
  _start() {
    const { delay, callback } = this;
    if (document.visibilityState === 'hidden') {
      this._startWokerInterval();
    } else if (document.visibilityState === 'visible') {
      this._preciseInterVal(callback, delay);
    } else {
      return;
    }
  }
  // requestAnimationFrame做的高精度定时器
  _preciseInterVal(callback, interval) {
    this.interValStatus = 'precise';
    this.immediate && callback(); // 立即为true才执行
    this.timer1 = setInterval(() => {
      callback();
    }, interval);
  }
  // 开启worker定时器
  _openWorkerInterval() {
    const { callback } = this;
    this.timer2 = new Worker(intervalWorker);
    this.timer2.onmessage = () => {
      callback();
    };
  }
  // 判断浏览器休眠
  _visibilitychange() {
    const { delay, callback, interValStatus } = this;
    if (document.visibilityState === 'hidden') {
      this._closePreciseInterVal();
      this._startWokerInterval();
    } else if (document.visibilityState === 'visible' && interValStatus === 'worker') {
      this._preciseInterVal(callback, delay);
      this._stopWokerInterval();
    } else {
      return;
    }
  }
  // 关闭request定时器
  _closePreciseInterVal() {
    clearInterval(this.timer1);
  }
  // 停止worker定时器
  _stopWokerInterval() {
    const { timer2 } = this;
    timer2.postMessage({ start: false });
  }
  // 开启worker定时器
  _startWokerInterval() {
    const { timer2, delay, interValStatus, immediate } = this;
    if (interValStatus === 'worker') {
      this._stopWokerInterval(); // 如果之前也是worker,那个之前的停止
    } else {
      this.interValStatus = 'worker';
    }
    timer2.postMessage({ start: true, delay, immediate });
  }
  // 关闭worker定时器
  _closeWorkerInterVal() {
    const { timer2 } = this;
    if (timer2) {
      this._stopWokerInterval();
      timer2.terminate();
      this.timer2 = null;
    }
  }
  // 关闭定时器
  close() {
    this._closePreciseInterVal();
    this._closeWorkerInterVal();
    document.removeEventListener('visibilitychange', this.copyFunc);
  }
}

export default PreciseInterval;
/*公用的worker定时器*/
const workercode = () => {
  let timer = null;
  onmessage = e => {
    // 开启定时器
    const { start, delay = null, immediate = null } = e.data;
    if (start) {
      immediate && postMessage('1'); // 判断是否立即执行
      timer = setInterval(() => {
        postMessage('1');
      }, delay);
    } else {
      clearInterval(timer);
    }
  };
};

let code = workercode.toString();
code = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'));

const blob = new Blob([code], { type: 'application/javascript' });
const intervalWorker = URL.createObjectURL(blob);
